#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <strings.h>
#include <errno.h>

#include "uart_send.h"
#include "include/fmux.h"

#define MAX_TEST_LEN	16

int SERIAL_FD;

void usage(int argc, char * argv[]) {
	printf("%s -s <Serial Device> [-h]\n", argv[0]);
}

struct comm_test_unit {
	uint8_t size;
	uint8_t cmd;
	uint8_t data[MAX_TEST_LEN];
};

uint8_t fill_struct(struct comm_test_unit * u, uint8_t cmd, char * data) {
	u->cmd = cmd;
	size_t i = 0;
	do {
		u->data[i] = data[i];
		i++;
	} while (i < MAX_TEST_LEN && data[i-1] != '\0');
	u->size = i;

	if (i == MAX_TEST_LEN) {
		fprintf(stderr, "Test string too long.\n");
		return 0;
	}
	return 1;
}

void send_struct(struct comm_test_unit * u) {
	//printf("%ld %ld\n", sizeof(struct comm_test_unit), t_unit.size);
	if (u->size > 0)
		printf("sending: %s\n", u->data);
	uart_send((struct comm_unit *) u);
	printf("done\n");
	uint8_t tmp_size = u->size;
	bzero(u, sizeof(struct comm_test_unit));
	uart_recv((struct comm_unit *) u, tmp_size);
	if (u->size > 0)
		printf("got: %s\n", u->data);
}

int main(int argc, char * argv[]) {
	int opt;

	while ((opt = getopt(argc, argv, "s:h")) != -1) {
		switch (opt) {
			case 's' : {
				SERIAL_FD = open(optarg, O_RDWR, S_IRUSR | S_IWUSR);
				if (SERIAL_FD == -1) {
					fprintf(stderr, "Open failed: %s\n", strerror(errno));
					return 2;
				}
				break;
			}
			case 'h' :
			default : {
				usage(argc, argv);
				return 2;
			}
		}
	}

	if (SERIAL_FD == 0) {
		usage(argc, argv);
		return 2;
	}

	printf("SERIAL_FD: %d\n", SERIAL_FD);

	struct comm_test_unit t_unit;

	char * test_strings[] = {
		"abcdef",
		"g",
		"hijklmnopq",
		"rstuvwxyz"
	};

	printf("%d\n", sizeof(test_strings)/sizeof(char *));

	// test some strings
	for (int i = 0; i < (sizeof(test_strings)/sizeof(char *)); i++) {
		if (fill_struct(&t_unit, OTPLATRADIOSETPANID, test_strings[i])) {
			send_struct(&t_unit);
			if (0 != strncmp(test_strings[i], t_unit.data, MAX_TEST_LEN)) {
				printf("Error in round %d\n", i);
			}
		}
	}

	// test empty
	t_unit.size = 0;
	t_unit.cmd = OTPLATRADIOSETPANID;
	send_struct(&t_unit);
}
